package scfg.utils;

import java.util.*;
import java.util.Map.Entry;
import java.io.*;

import scfg.output.Display;
import desposito6.utils.CommandLine;

public class DuplicateFinder {

	public static Map<String, List<String>> ht;
	private static Display output;

	static {
		output = new Display("DuplicateFinder");
	}

	public static boolean processFile(File f) {
		if (f == null || !f.exists() || !f.getName().endsWith(".rna"))
			return false;
		boolean rtn = false;
		try {
			Scanner scan = new Scanner(f);
			String seq = scan.nextLine();
			scan.close();
			List<String> list = ht.get(seq);
			if (list == null) {
				list = new ArrayList<String>();
				ht.put(seq, list);
			} else
				rtn = true;
			list.add(f.getAbsolutePath());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return rtn;
	}

	public static void processDir(String filename, List<String> duplicateFiles) {
		if (filename == null)
			return;
		processDir(new File(filename), duplicateFiles);
	}

	public static List<String> processDir(File base, List<String> duplicateFiles) {
		if (!base.exists())
			return null;
		File[] files = base.listFiles();
		for (File f : files) {
			if (f.isDirectory())
				processDir(f, duplicateFiles);
			else
				if(processFile(f))
					duplicateFiles.add(f.getAbsolutePath());
		}
		return duplicateFiles;
	}

	public static void duplicateMover(List<String> duplicateFiles,
			String destDir) {
		if (duplicateFiles == null) {
			return;
		}
		int count = 0;
		File destDirFile = new File(destDir);
		if (!destDirFile.exists())
			destDirFile.mkdir();
		try {
			for (String filename : duplicateFiles) {
				File orig = new File(filename);
				if (filename.endsWith(".rna") && orig.exists()) {
					String dest = destDir + "/" + orig.getName();
					Process p = Runtime.getRuntime().exec(
							new String[] { "/bin/sh", "-c",
									"cp " + filename + " " + dest });
					p.waitFor();
					if (!(new File(dest).exists())) {
						output.out("\tERROR: " + filename);
					}
				} else
					output.out((count++) + "\tSKIPPING: " + filename);
			}
		} catch (IOException e) {
		} catch (InterruptedException e) {
		}
	}

	public static void duplicateDeleter(List<String> ambiguousFiles) {
		if (ambiguousFiles == null) {
			return;
		}
		int count = 0;
		try {
			for (String filename : ambiguousFiles) {
				File orig = new File(filename);
				if (filename.endsWith(".rna") && orig.exists()) {
					Process p = Runtime.getRuntime().exec(
							new String[] { "/bin/sh", "-c", "rm " + filename });
					p.waitFor();
					if (new File(filename).exists())
						output.out("\tERROR: " + filename);
				} else
					output.out((count++) + "\tSKIPPING: " + filename);
			}
		} catch (IOException e) {
		} catch (InterruptedException e) {
		}
	}

	public static void printList(List<String> duplicateFiles) {
		try {
			output.out("\n\n[DELETE LIST]\n-------------\n");
			for (String s : duplicateFiles) {
				output.out(s);
				output.out("\n");
			}
			output.out("\n\n[DUPLICATE LIST]\n----------------\n");
			for (Entry<String, List<String>> me : ht.entrySet()) {
				if (me.getValue().size() > 1) {
					output.out("SET = {\n");
					for (String s : me.getValue()) {
						output.out("\t");
						output.out(s);
						output.out("\n");
					}
					output.out("\t};\n\n");
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static String helpMessage() {
		return "\n[scfg.utils.StructureAggregator]\n\t"
				+ "* -h Display help message.\n\t" + "* -s Source folder.\n\t"
				+ "* -d Destination folder - Copy. (Optional)\n\t"
				+ "* -delete Delete ambiguous files. (Optional)"
				+ "* -o Output filename. (Optional)\n\t"
				+ "* -c Generate compressed file. (Optional)"
				+ "* -v Display verbose output. (Optional)\n\n";
	}

	/**
	 * <pre>
	 * -h Display help message.
	 * -s Source folder.
	 * -d Destination folder - Copy. (Optional)
	 * -delete Delete ambiguous files. (Optional)
	 * -o Output filename. (Optional)
	 * -c Generate compressed files. (Optional)
	 * -v Display verbose output. (Optional)
	 * </pre>
	 * 
	 * -s /home/david/Documents/REU/RNA/rna_files/ -d
	 * /home/david/Documents/REU/RNA/ambiguous_files/ -v
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		ht = new HashMap<String, List<String>>();

		if (CommandLine.containsArg(args, "-h") >= 0) {
			output.out(helpMessage());
			output.finalizeDisplay();
			return;
		}
		int temp = CommandLine.containsArg(args, "-o");
		if (temp >= 0 && temp < args.length - 1) {
			output = new Display(args[temp + 1], args[temp + 1] + "_error.log",
					true);
		}
		temp = CommandLine.containsArg(args, "-s");
		String sourceName = null;
		if (temp >= 0 && temp < args.length - 1) {
			sourceName = args[temp + 1];
		}
		temp = CommandLine.containsArg(args, "-d");
		String destinationName = null;
		if (temp >= 0 && temp < args.length - 1) {
			destinationName = args[temp + 1];
		} else {
			destinationName = ".ambiguous_rna/";
		}
		output.setVerbose(CommandLine.containsArg(args, "-v") >= 0);
		File srcFile = new File(sourceName);
		List<String> duplicateFiles = processDir(srcFile,
				new ArrayList<String>());
		if (destinationName != null)
			duplicateMover(duplicateFiles, destinationName);
		if (CommandLine.containsArg(args, "-delete") >= 0)
			duplicateDeleter(duplicateFiles);
		printList(duplicateFiles);
		output.out("\n\n\n\t[EXITING StructureAggregator.main]");
		output.finalizeDisplay();
	}

}
